import { deepClone } from "../utils/common";
import * as componentChild from "./slots";
import { defineComponent, h } from "vue";

export default defineComponent({
  props: {
    conf: {
      type: Object,
      required: true,
    },
  },
  setup(props, { slots, emit }) {
    const makeDataObject = () => {
      return {
        class: {},
        attrs: {},
        props: {},
        domProps: {},
        nativeOn: {},
        on: {},
        style: {},
        directives: [],
        scopedSlots: {},
        slot: null,
        key: null,
        ref: null,
        refInFor: true,
      };
    };
    const buildDataObject = (confClone, dataObject) => {
      Object.keys(confClone).forEach((key) => {
        const val = confClone[key];
        if (key === "__vModel__") {
          vModel(dataObject, confClone.__config__.defaultValue);
        } else if (dataObject[key] !== undefined) {
          if (
            dataObject[key] === null ||
            dataObject[key] instanceof RegExp ||
            ["boolean", "string", "number", "function"].includes(
              typeof dataObject[key]
            )
          ) {
            dataObject[key] = val;
          } else if (Array.isArray(dataObject[key])) {
            dataObject[key] = [...dataObject[key], ...val];
          } else {
            dataObject[key] = { ...dataObject[key], ...val };
          }
        } else {
          dataObject.attrs[key] = val;
        }
      });
      // 清理属性
      clearAttrs(dataObject);
    };
    const vModel = (dataObject, defaultValue) => {
      dataObject.props.value = defaultValue;
      dataObject.on.input = (val) => {
        emit("input", val);
      };
    };
    // 定义一个函数 mountSlotFiles，用于挂载插槽文件
    const mountSlotFiles = (h, confClone, children) => {
      // 从 componentChild 对象中获取与 confClone.__config__.tag 对应的子组件对象
      const childObjs = componentChild[confClone.__config__.tag];
      if (childObjs) {
        Object.keys(childObjs).forEach((key) => {
          const childFunc = childObjs[key];
          if (confClone.__slot__ && confClone.__slot__[key]) {
            children.push(childFunc(h, confClone, key));
          }
        });
      }
    };
    const emitEvents = (confClone) => {
      ["on", "nativeOn"].forEach((attr) => {
        const eventKeyList = Object.keys(confClone[attr] || {});
        eventKeyList.forEach((key) => {
          const val = confClone[attr][key];
          if (typeof val === "string") {
            confClone[attr][key] = (event) => emit(val, event);
          }
        });
      });
    };
    const clearAttrs = (dataObject) => {
      delete dataObject.attrs.__config__;
      delete dataObject.attrs.__slot__;
      delete dataObject.attrs.__methods__;
    };

    const dataObject = makeDataObject();
    const confClone = deepClone(props.conf);
    const children = slots.default || [];

    // 如果slots文件夹存在与当前tag同名的文件，则执行文件中的代码
    mountSlotFiles(h, confClone, children);

    // 将字符串类型的事件，发送为消息
    emitEvents(confClone);

    // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
    buildDataObject(confClone, dataObject);
    // 第一个参数要是组件 可以使用component
    // const component = resolveDynamicComponent(props.conf.__config__.tag);
    return h(props.conf.__config__.tag, dataObject, children);
  },
});
